/*************************************************************************
 *
 *  $RCSfile: counter.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2005/01/31 17:06:40 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  the BSD license.
 *
 *  Copyright (c) 2003 by Sun Microsystems, Inc.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *  1. Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *  3. Neither the name of Sun Microsystems, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
 *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *************************************************************************/

/***************************************************************************************************
 ***************************************************************************************************
 *
 * service implementation:	 iapart.TabBrowse
 * exported interfaces:		 iapart.ITabBrowse
 *
 * task creator service
 *
 ***************************************************************************************************
 **************************************************************************************************/


/*
  01-08-2005
  * Removed most of Andreas' comments
  * Added WindowAttribute::SIZEABLE
  * Added XWindowListener implementation, but without success
  * Tried to add an instance of the TabWindowFactory, without success due to
    compilation problems.
*/
//#include <stdio.h>
//#include <stdio.h>
#include <cstdlib>
#include <list>
#include <rtl/uuid.h>
#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif

#ifndef _CPPUHELPER_QUERYINTERFACE_HXX_
#include <cppuhelper/queryinterface.hxx> // helper for queryInterface() impl
#endif
#ifndef _CPPUHELPER_FACTORY_HXX_
#include <cppuhelper/factory.hxx> // helper for component factory
#endif

#include <cppuhelper/implbase.hxx>
#include <cppuhelper/implbase1.hxx>
#include <cppuhelper/implbase2.hxx>
#include <cppuhelper/implbase3.hxx>
#include <cppuhelper/implbase4.hxx>
#include <cppuhelper/implbase5.hxx>
#include <cppuhelper/implbase6.hxx>
#include <cppuhelper/implbase7.hxx>
//#include <cppuhelper/implbase
// generated c++ interfaces
#ifndef _COM_SUN_STAR_LANG_XSINGLESERVICEFACTORY_HPP_
#include <com/sun/star/lang/XSingleServiceFactory.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
#include <com/sun/star/lang/XServiceInfo.hpp>
#endif
#ifndef _COM_SUN_STAR_REGISTRY_XREGISTRYKEY_HPP_
#include <com/sun/star/registry/XRegistryKey.hpp>
#endif
#include <com/sun/star/frame/XDesktop.hpp>
#include <com/sun/star/awt/WindowAttribute.hpp>
#include <com/sun/star/awt/XToolkit.hpp>
#include <com/sun/star/frame/XFrame.hpp>
#include <com/sun/star/awt/WindowDescriptor.hpp>
#include <com/sun/star/awt/XWindowPeer.hpp>
#include <com/sun/star/awt/XWindow.hpp>
#include <com/sun/star/frame/XComponentLoader.hpp>
#include <com/sun/star/frame/XLayoutManager.hpp>
#include <com/sun/star/frame/XFrameActionListener.hpp>
//#include <com/sun/star/frame/
#include <com/sun/star/awt/WindowEvent.hpp>
#include <com/sun/star/awt/XWindowListener.hpp>
#include <com/sun/star/awt/XTopWindowListener.hpp>
//#include <com/sun/star/awt/XTopWindow.hpp>
#include <com/sun/star/awt/XMessageBox.hpp>
#include <com/sun/star/ui/XUIElement.hpp>
#include <com/sun/star/awt/XExtendedToolkit.hpp>
#include <com/sun/star/awt/XMenuBar.hpp>
#include <com/sun/star/util/XCloseListener.hpp>
#include <com/sun/star/util/XCloseBroadcaster.hpp>
#include <com/sun/star/frame/XDispatchHelper.hpp>
#include <com/sun/star/frame/XDispatchProvider.hpp>
#include <com/sun/star/util/XCloseable.hpp>
//#include <com/sun/star/uno/Type.hpp>
//#include <com/sun/star/util/clo
// for the tab control

#include <com/sun/star/lang/XSingleComponentFactory.hpp>
#include <com/sun/star/awt/XSimpleTabController.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/awt/XTabListener.hpp>
/* ********************************************************* */

//#include "cTabList.hpp"

/* ********************************************************* */


#define SERVICENAME "iapart.TabBrowse"
#define IMPLNAME	"com.sun.star.comp.apart.cpp.TabBrowse"
#define DEBUG	0

#include <iapart/ITabBrowse.hpp>

namespace css = ::com::sun::star;

using namespace std;
using namespace ::rtl;
using namespace ::osl;
using namespace ::cppu;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::registry;
using namespace ::com::sun::star::awt;
using namespace ::com::sun::star::frame;

class cMyWindow;

//===================================================================================

typedef struct
{
       long m_cID;
       Reference< XWindow > m_cWindow;
	Reference< XFrame > m_cFrame;
	Reference< XMenuBar > m_cMenu;
} sChild;
typedef sChild sChildTabs;


//===================================================================================
/* Trick to get an initialized mutex member, which can be used during the ctor too!
*/


struct tLockable
{
    public:
        ::osl::Mutex m_aLock;
};


//===================================================================================

typedef ::cppu::WeakImplHelper1< ::com::sun::star::awt::XTabListener > TabListenerHelper;
class TabListenerImpl : public TabListenerHelper
{
	Reference< XInterface >  m_xParent;
	Reference< ::iapart::ITabBrowse > m_xParentAW;
      public:
		long pActiveID;
        	TabListenerImpl() {};
        	TabListenerImpl(const Reference< XInterface >& xParentInt)
		{
			pActiveID=0;
			m_xParent = xParentInt;
			m_xParentAW = Reference< ::iapart::ITabBrowse >(m_xParent, UNO_QUERY);
			if(!m_xParentAW.is()) printf("--- tablistener couldn't query parent for ITabBrowse interface ---\n");
			else if(DEBUG>1)  printf("--- tablistener obtained ITabBrowse interface :-) ---\n");
		};
		~TabListenerImpl() {

			if(DEBUG)
				 printf("--- tablistener dtor called ---\n");
		
			m_xParent.clear(); 
			m_xParentAW.clear();
		};

             virtual void SAL_CALL disposing (const ::com::sun::star::lang::EventObject& aEObj)
                     throw(::com::sun::star::uno::RuntimeException) {
			m_xParent.clear();
			m_xParentAW.clear();
			if(DEBUG>1)
			printf("object TabListener listened to is disposing! refCount=%d\n", m_refCount);
                     }
             virtual void SAL_CALL inserted(long ID)
		throw(::com::sun::star::uno::RuntimeException)
             {
                     // tabList->Add(ID)
			  pActiveID = ID;
			  m_xParentAW->showChildWindow(ID);

                          if(DEBUG>1)printf("--- TAB id=%ld inserted ---\n", ID);
                     }

             virtual void SAL_CALL removed(long ID) throw(::com::sun::star::uno::RuntimeException){ if(DEBUG>1)printf("--- Tab %ld removed ---\n", ID); fflush(stdout);};
             virtual void SAL_CALL changed(long ID, const Sequence< com::sun::star::beans::NamedValue >& Props)
                          throw(::com::sun::star::uno::RuntimeException) {};
                          
             virtual void SAL_CALL activated(long ID)
		throw(::com::sun::star::uno::RuntimeException)
		{
 			pActiveID = ID;
               	        m_xParentAW->showChildWindow(ID);

			if(DEBUG>1)
				printf("--- TAB id=%ld activated ---\n", ID);

		};


             virtual void SAL_CALL deactivated(long ID)
		throw(::com::sun::star::uno::RuntimeException)
             {
                     // unset internal Window ID
                     // m_xMyWin->hideChildWindow(ID);
			 m_xParentAW->hideChildWindow(ID);

		         if(DEBUG>1)
				printf("--- TAB id=%ld deactivated ---\n", ID);

             }
      };
// ==========================================================================================

class cMyWindow	: private tLockable,
		 public ::cppu::WeakImplHelper6< ::css::awt::XWindowListener, 
						::css::awt::XTopWindowListener,
//						::css::util::XCloseListener,
						::css::frame::XFrameActionListener,
						XServiceInfo,
						XSingleServiceFactory,
						::iapart::ITabBrowse >
{
	long m_xActiveID;
	long m_xWidth;
	long m_xHeight;
	::std::list< sChildTabs > m_xChildren; // list of the child windows

	Reference< XFrameActionListener > m_xFrameActionListener;
	Reference< XTabListener > m_xTabListener;

	Reference< XMultiServiceFactory > m_xServiceManager;

	Reference< XInterface > m_xTabFactory;
	Reference< XSimpleTabController >  m_xTabControl; // { service css::awt::XSimpleTabController };
	
	Reference< XWindow > m_xTabParentWindow;
   	Reference< XTopWindow > m_xTopWindow;
 
	Reference< XToolkit > m_xToolkit;
	Reference< XDesktop > m_xDesktop;
 

    
public:
	cMyWindow* pNew;
	cMyWindow( const Reference< XMultiServiceFactory > & xServiceManager );
	~cMyWindow() {
                	if(DEBUG)
				printf( "< cMyWindow dtor called >\n" ); 
	}

    // XServiceInfo	implementation
	virtual OUString SAL_CALL getImplementationName(  ) throw(RuntimeException);
	virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) throw(RuntimeException);
	virtual Sequence< OUString > SAL_CALL getSupportedServiceNames(  ) throw(RuntimeException);
	static Sequence< OUString > SAL_CALL getSupportedServiceNames_Static(  );

    // XSingleServiceFactory implementation needed by the task creator
	virtual Reference< css::uno::XInterface > SAL_CALL createInstance()
	        throw(css::uno::Exception       ,
	              css::uno::RuntimeException);

	virtual Reference< css::uno::XInterface > SAL_CALL createInstanceWithArguments(const css::uno::Sequence< css::uno::Any >& lArguments)
		throw(css::uno::Exception ,
        	css::uno::RuntimeException);

	void implLateInit();
	virtual void addChildWindow(sChildTabs w); // I don't really know if those methods should be virtual.
	virtual Reference< XWindow> findChildWindow(long ID);
	virtual void SAL_CALL showChildWindow(long ID) throw(css::uno::RuntimeException);
	virtual void SAL_CALL hideChildWindow(long ID) throw(css::uno::RuntimeException);
	virtual void SAL_CALL resizeActiveChild(long width, long height) throw(css::uno::RuntimeException);
	virtual void SAL_CALL removeChildWindow(long ID)throw(css::uno::RuntimeException){};
  


// XWindowListener implementation


	virtual void SAL_CALL windowResized(const ::com::sun::star::awt::WindowEvent& e)
                throw(::com::sun::star::uno::RuntimeException)
              		{
				::osl::ResettableMutexGuard aLock(m_aLock);

				m_xWidth = e.Width;
				m_xHeight = e.Height;
                		resizeActiveChild(e.Width, e.Height);         
                		if(DEBUG>2)printf("\t(=)\tWindow Resized\n");
                      		aLock.clear();

                		}
	virtual void SAL_CALL windowMoved(const ::com::sun::star::awt::WindowEvent& e)
                throw(::com::sun::star::uno::RuntimeException){};
	virtual void SAL_CALL windowShown(const ::com::sun::star::lang::EventObject& e)
                throw(::com::sun::star::uno::RuntimeException){
                     if(DEBUG>2)printf("=== Window Shown ===\n");                                               
        	        };
	virtual void SAL_CALL windowHidden(const ::com::sun::star::lang::EventObject& e)
                throw(::com::sun::star::uno::RuntimeException){
                      if(DEBUG>2)printf("=== Window Hidden ===\n");
                	};

// XTopWindowListener
	virtual void SAL_CALL windowOpened(const ::css::lang::EventObject& e) throw(::css::uno::RuntimeException){if(DEBUG>2) printf("--- Top Window Opened ---\n");};
	virtual void SAL_CALL windowClosing(const ::css::lang::EventObject& e) throw(::css::uno::RuntimeException){if(DEBUG>2)printf("--- Top Window Closing ---\n");};
	virtual void SAL_CALL windowClosed(const ::css::lang::EventObject& e) throw(::css::uno::RuntimeException){if(DEBUG>2)printf("--- Top Window Closed ---\n");};
	virtual void SAL_CALL windowMinimized(const ::css::lang::EventObject& e) throw(::css::uno::RuntimeException){if(DEBUG>2)printf("--- Top Window Minimized ---\n");};
	virtual void SAL_CALL windowNormalized(const ::css::lang::EventObject& e) throw(::css::uno::RuntimeException){if(DEBUG>2)printf("--- Top Window Normalized ---\n");};
	virtual void SAL_CALL windowActivated(const ::css::lang::EventObject& e) throw(::css::uno::RuntimeException){if(DEBUG>2)printf("--- Top Window Activated---\n");};
	virtual void SAL_CALL windowDeactivated(const ::css::lang::EventObject& e) throw(::css::uno::RuntimeException){if(DEBUG>2)printf("--- Top Window Deavctivated---\n");};

// XFrameActionListener
	virtual void SAL_CALL frameAction(const ::css::frame::FrameActionEvent& e) throw(::css::uno::RuntimeException);
	virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& e) 
		throw(::com::sun::star::uno::RuntimeException);
	

	virtual void SAL_CALL closeFrame( Reference< XFrame > childFrame ); 
};


//*************************************************************************

cMyWindow::cMyWindow( const Reference< XMultiServiceFactory > & xServiceManager )
		: m_xServiceManager( xServiceManager ) 
		{
			if(DEBUG)
				printf( "< cMyWindow ctor called >\n" );
			if(DEBUG)
				printf("this is the new version 0.1.0\n");
	if ( ! m_xServiceManager.is() )
        throw css::uno::RuntimeException(
                ::rtl::OUString::createFromAscii("Cant live without an UNO Service manager."),
                static_cast< css::lang::XSingleServiceFactory* >(this));


	m_xActiveID = -1;
	m_xWidth=0;
	m_xHeight=0;

	m_xDesktop = Reference< XDesktop >(m_xServiceManager->createInstance(
		                OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop"))), UNO_QUERY_THROW);

	m_xToolkit = Reference< XToolkit >(m_xServiceManager->createInstance(
						OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.awt.Toolkit"))),UNO_QUERY_THROW);
 
	m_xTabFactory = Reference< XInterface > (m_xServiceManager->createInstance(
                              ::rtl::OUString::createFromAscii("com.sun.star.frame.TabWindowFactory")),UNO_QUERY_THROW); 
	Reference< XMultiServiceFactory > xMgr = m_xServiceManager;                             
	Reference< ::com::sun::star::beans::XPropertySet > xProps(xMgr, UNO_QUERY_THROW);
	Any aProp = xProps->getPropertyValue(::rtl::OUString::createFromAscii("DefaultContext"));
	Reference< XComponentContext > xDefaultContext;
    
	aProp >>= xDefaultContext;  // I like this. It's really slick.
    
	Reference< XSingleComponentFactory > xTabCompFactory (m_xTabFactory, UNO_QUERY_THROW);
	Reference< XInterface > xTabControl = xTabCompFactory->createInstanceWithContext(xDefaultContext);
	m_xTabControl = Reference< XSimpleTabController > (xTabControl, UNO_QUERY_THROW);
	if(DEBUG)
		 printf("*** cMyWindow ctor end ***\n");
}

//*************************************************************************

Reference< css::uno::XInterface > SAL_CALL cMyWindow::createInstance()
    throw(css::uno::Exception       ,
          css::uno::RuntimeException)
{
    return createInstanceWithArguments(css::uno::Sequence< css::uno::Any >());
}

//*************************************************************************

Reference< css::uno::XInterface > SAL_CALL cMyWindow::createInstanceWithArguments(const css::uno::Sequence< css::uno::Any >& lArguments)
    throw(css::uno::Exception       ,
          css::uno::RuntimeException)
{

	try
    {

        // That's why this rule: unlock your mutex everytime you call out !!! .-))

        ::osl::ResettableMutexGuard aLock(m_aLock);
            Reference< css::lang::XMultiServiceFactory > xFact    = m_xServiceManager;
            Reference< css::frame::XFramesSupplier >     xDesktop (m_xDesktop, css::uno::UNO_QUERY_THROW);
      
        aLock.clear();

        // Creation of services and querying interfaces can be combined.
	    	Reference< css::frame::XFrames > xContainer = xDesktop->getFrames();
		Reference< css::awt::XToolkit > xTk(
                       xFact->createInstance(::rtl::OUString::createFromAscii("com.sun.star.awt.Toolkit")),
                       css::uno::UNO_QUERY_THROW);

        
  //      Reference< css::frame::XFrame >    xFrameParent = Reference< XFrame >(
//                                                                        xFact->createInstance(
  //                                                                              OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Frame"))), UNO_QUERY_THROW);
 //       xFrameParent->initialize(m_xTabParentWindow);
 //       xFrameParent->setCreator(xDesktop);

	

        css::awt::WindowDescriptor wDesc;
        wDesc.Type              = WindowClass_SIMPLE;
        wDesc.WindowServiceName = OUString(RTL_CONSTASCII_USTRINGPARAM(""));
        wDesc.ParentIndex       = 0;
        wDesc.Parent            = Reference< XWindowPeer >(m_xTabParentWindow, UNO_QUERY_THROW);
        wDesc.Bounds            = (Reference< XWindow >(wDesc.Parent,UNO_QUERY_THROW))->getPosSize();
        wDesc.WindowAttributes  = WindowAttribute::CLOSEABLE; //| 
//                                  WindowAttribute::SIZEABLE; //  | WindowAttribute::SHOW; dont show windows on creation time! It has to be done later explicitly.
	Reference< css::frame::XFrame > xFrameChild(xFact->createInstance(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Frame"))), UNO_QUERY_THROW);
        Reference< css::awt::XWindowPeer > xPeerChild = xTk->createWindow(wDesc);
        Reference< css::awt::XWindow >     xWindow1(xPeerChild, UNO_QUERY_THROW);
	

 	xFrameChild->setName(	::rtl::OUString::createFromAscii("my window") + 
			 	::rtl::OUString::valueOf((sal_Int32)m_xChildren.size()));
	
	xFrameChild->initialize(xWindow1);
//	Reference< XComponent > xC(xFrameChild, UNO_QUERY);

//	xC->addEventListener(m_xDisposeListener);
	xFrameChild->addFrameActionListener(
				Reference< XFrameActionListener > (
					static_cast<XSingleServiceFactory *> (this),
					 UNO_QUERY)
				);

        xWindow1->setVisible((sal_Bool)true);
//	xWindow1->addWindowListener(m_xResizeListener);
	xContainer->append(xFrameChild);
	xFrameChild->setCreator(xDesktop);

	
        long t1ID = m_xTabControl->insertTab();
                
        sChildTabs sCW;
        
        sCW.m_cID = t1ID;
	sCW.m_cFrame = xFrameChild;
        sCW.m_cWindow = xWindow1;
	
        addChildWindow(sCW);
       
        Sequence< css::beans::NamedValue > props(1);
        
	
        props[0].Name = ::rtl::OUString::createFromAscii("Title");
        props[0].Value= makeAny(xFrameChild->getName());
        m_xTabControl->setTabProps(t1ID, props);
	m_xTabControl->activateTab(t1ID);
        return Reference< css::uno::XInterface >(xFrameChild, css::uno::UNO_QUERY_THROW);


    }
    catch(const css::uno::RuntimeException& exRuntime)
    {
        throw exRuntime;
    }
    catch(const css::uno::Exception& exAny)
	{
		OString s = OUStringToOString(exAny.Message, RTL_TEXTENCODING_ASCII_US);
		fprintf(stderr, "Error: %s\n", s.pData->buffer);
	}
    return Reference< css::uno::XInterface >();
}

 void SAL_CALL cMyWindow::disposing (const ::com::sun::star::lang::EventObject& e) 
	throw(::com::sun::star::uno::RuntimeException) {
		
		if(DEBUG>1) {
				printf("listener caught disposing of some object\n");
				printf("m_refcount=%d\n", m_refCount);
				}
				
		if(e.Source == m_xTopWindow) // Top window's close button pressed
		{
			if(DEBUG)
				printf("\t(*)\tlistener caught disposing of the Top Window\n");
//		        ::osl::ResettableMutexGuard aLock(m_aLock);
			m_xTopWindow.clear();
//			aLock.clear();
		}
		else if(e.Source == m_xTabParentWindow)
		{
			if(DEBUG)
				printf("\t(*)\tlistener caught disposing of Tab Parent\n");
			if(m_xDesktop->terminate()) {
				if(DEBUG)
					printf("DESKTOP TERMINATE=TRUE\n");
				Reference< XComponent > xC(m_xTabControl, UNO_QUERY);
				if(xC.is() && m_xTabControl.is()) {
					xC->dispose();
					if(DEBUG>1)
						printf("TABCONTROL DISPOSED\n");fflush(stdout);
					} else if(DEBUG>1)
						 printf(" TABCONTROL ALREADY BEEN DISPOSED \n");
				}

		        ::osl::ResettableMutexGuard aLock(m_aLock);

			m_xTabParentWindow.clear();
			m_xTabListener.clear();
			m_xTabFactory.clear();

			aLock.clear();
			}
				// else - it's probably a childFrame, so find it and close the tab
		else {
			Reference< XFrame > childFrame (e.Source, UNO_QUERY);
			
			closeFrame(childFrame);  // moved out to closeFrame method	
			if(m_xChildren.size()==0)
			{
				Reference< XComponent > xC;
				if(m_xTabControl.is()){
					xC = Reference< XComponent > (m_xTabControl,UNO_QUERY);
					if(xC.is())
						xC->dispose();
				}
	
				::osl::ResettableMutexGuard aLock(m_aLock);

				m_xTabListener.clear();
				m_xTabControl.clear();
				m_xTabFactory.clear();
				m_xFrameActionListener.clear();
		
				aLock.clear();

			}
		}
						// if we got here - I don't know what's being disposed
		
   if(DEBUG)
		printf("\t(*)\tm_refCount=%d\n",m_refCount);
 }


void SAL_CALL cMyWindow::frameAction(const ::css::frame::FrameActionEvent& e) throw(::css::uno::RuntimeException){
	if(DEBUG>1)	printf("*** frame Action EVENT ! ***\n");
			Reference< XFrame > xFrame(e.Frame);

		if(e.Action == 0)
		{
//			if(e.Frame == m_xChildren[0].m_cFrame);
		if(DEBUG>1)	printf("xxx caught COMPONENT_ATTACHED event ! will deregister myself ! xxx\n ");

			Reference< css::beans::XPropertySet > xFrameProp(xFrame, UNO_QUERY_THROW);
			Reference< XLayoutManager > xLayout;
			Any aProp = xFrameProp->getPropertyValue(::rtl::OUString::createFromAscii("LayoutManager"));
			aProp >>= xLayout;

			if(!xLayout.is()) 
				 printf("*** failed to retrieve XLayoutManager :-( ***\n");
			else if(DEBUG>2) printf("*** XLayoutManager retrieved properly ***\n");

		//	css::ui::XUIElement xEl;
			Reference< css::ui::XUIElement > xMenu (xLayout->getElement(::rtl::OUString::createFromAscii("private:resource/menubar/menubar")));

			if(! xMenu.is()) {
					if(DEBUG>1) {
						printf("*** couldn't retrieve xMenu :-( ***\n");
						printf("*** trying to create the menubar ***\n");
						}

					xLayout->createElement(::rtl::OUString::createFromAscii("private:resource/menubar/menubar"));
					xMenu = Reference<css::ui::XUIElement >(xLayout->getElement(::rtl::OUString::createFromAscii("private:resource/menubar/menubar")));
					if(!xMenu.is()) printf("*** still no joy :-( ***\n");
					else if(DEBUG>1) printf("*** properly retrieved xMenu this time ***\n");

				}
				
			if(xMenu.is()) {
				
				Reference< css::beans::XPropertySet > xUIElProps (xMenu, UNO_QUERY);
				Reference< XMenuBar > menuBar;
				aProp = xUIElProps->getPropertyValue(::rtl::OUString::createFromAscii("XMenuBar"));
				aProp >>=menuBar;
				if(menuBar.is())
				{
					if(DEBUG>1) printf("*** XMenuBar retrieved properly ***\n");
		        	   ::std::list< sChildTabs >::iterator childListIter;
			           for(childListIter = m_xChildren.begin(); childListIter != m_xChildren.end(); childListIter++)
			           {
//					Reference< XFrame > fr;// = (*childListIter).m_cFrame;
					
                			   if( (*childListIter).m_cFrame  == xFrame)
						{
							aProp >>=(*childListIter).m_cMenu;
							if(!(*childListIter).m_cMenu.is())
								printf("*** couldn't initiate child wth xMenu ***\n");
							else if(DEBUG>1) printf("*** successfully initiated the child with xMenu ***\n");
							break;
						}
			           }

//					Reference< XTopWindow > tabTop(m_xTabParentWindow, UNO_QUERY);
//					tabTop->setMenuBar(menuBar);
				}
			}	
			
		} else if(e.Action == 1)
		{
			if(DEBUG>1)
				printf("*** COMPONENT_DETACHING !\n");
			// find the Tab and clear it's m_cMenu
		
		}
		else if(e.Action ==2)
		{
			if(DEBUG>1)
				printf("*** COMPONENT_REATACHING ***\n");
			// update the tab's m_cMenu
		}
		else if(e.Action ==4)
		{
			if(DEBUG>1)
				printf("--- Frame deactivating ---\n");
		}
	}


 void SAL_CALL cMyWindow::closeFrame(Reference< XFrame > childFrame)
 {
	::std::list< sChildTabs >::iterator childListIter;
	for(childListIter = m_xChildren.begin(); childListIter != m_xChildren.end(); childListIter++)
	{
		if(childFrame == (*childListIter).m_cFrame)
		{
			if(DEBUG)
				printf("*** child frame of tab=%ld disposing, removing tab. ***\n", (*childListIter).m_cID);

		        ::osl::ResettableMutexGuard aLock(m_aLock);

			(*childListIter).m_cFrame.clear();
			(*childListIter).m_cWindow.clear();
			(*childListIter).m_cMenu.clear();

			aLock.clear();

			try {
				m_xTabControl->removeTab((*childListIter).m_cID);	
			} catch(Exception& e) {
				printf("\t(!)\tremove Tab has thrown an exception !\n");
			}

			m_xChildren.erase(childListIter);
			break;
		}
	}
 }

void cMyWindow::addChildWindow(sChildTabs w)
{
	m_xChildren.push_back(w);
	m_xActiveID = w.m_cID;
 }

Reference< XWindow > cMyWindow::findChildWindow(long ID)
{
	::std::list< sChildTabs >::const_iterator childListIter;
	for(childListIter = m_xChildren.begin(); childListIter != m_xChildren.end(); childListIter++)
	{
		if((*childListIter).m_cID == ID )
		return (*childListIter).m_cWindow;
	}

	return NULL;
}

void SAL_CALL cMyWindow::hideChildWindow(long ID)
throw(css::uno::RuntimeException)
{
     Reference< XWindow > child = findChildWindow(ID);
	if(child!=NULL) child->setVisible((sal_Bool)false);
 }
 
void SAL_CALL cMyWindow::showChildWindow(long ID)
throw(css::uno::RuntimeException)
{
	if(DEBUG>2) 
		printf("\t(*)\tTabBrowse running showChildWindow(%ld)\n", ID);
	sChildTabs* child = NULL;

          ::std::list< sChildTabs >::const_iterator childListIter;
           for(childListIter = m_xChildren.begin(); childListIter != m_xChildren.end(); childListIter++)
           {
                if((*childListIter).m_cID == ID )
		{	childListIter;
		
	
		m_xActiveID = ID;
 		resizeActiveChild(m_xWidth, m_xHeight);
		 ((*childListIter).m_cWindow)->setVisible((sal_Bool)true);

		if(((*childListIter).m_cMenu).is())
		{
			if(DEBUG>1) 
				printf("\t(*)\tmenu for this child retrieved properly\n");
			if(m_xTopWindow.is())
			{
				if(DEBUG>1)
					printf("\t(*)topwindow interface obtained\n");

//			TopWindow->setMenuBar bug - commented out
//			xTopWin->setMenuBar(((*childListIter).m_cMenu));
			}
			else printf("*** couldn't obtain topwindow :-( ***\n");
		} else if(DEBUG) printf("*** XMenuBar for this child is not set :-( ***\n");
	   }
	}

 }

void SAL_CALL cMyWindow::resizeActiveChild(long width, long height)
	throw(css::uno::RuntimeException)
{
	if(m_xActiveID != -1) {
		if(DEBUG>2) printf("*** going to set child window %ld size to (%ld,%ld) ***\n", m_xActiveID, width, height);
		// 3 flags POS
		// 12 flags only the size of the window.
		// 15 flags both - POS | SIZE
		Reference< XWindow > child = findChildWindow(m_xActiveID);
		if(child!=NULL) child->setPosSize(0,0,width,height,15); 
	}

} 

OUString SAL_CALL cMyWindow::getImplementationName(  )
	throw(RuntimeException)
{
	return OUString( RTL_CONSTASCII_USTRINGPARAM(IMPLNAME) );
}

//*************************************************************************
sal_Bool SAL_CALL cMyWindow::supportsService( const OUString& ServiceName )
	throw(RuntimeException)
{
	Sequence< OUString > aSNL = getSupportedServiceNames();
	const OUString * pArray = aSNL.getArray();
	for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
		if( pArray[i] == ServiceName )
			return sal_True;
	return sal_False;
}

//*************************************************************************
Sequence<OUString> SAL_CALL cMyWindow::getSupportedServiceNames(  )
	throw(RuntimeException)
{
	return getSupportedServiceNames_Static();
}

//*************************************************************************
Sequence<OUString> SAL_CALL cMyWindow::getSupportedServiceNames_Static(  )
{
	OUString aName( RTL_CONSTASCII_USTRINGPARAM(SERVICENAME) );
	return Sequence< OUString >( &aName, 1 );
}




/**
 * Function to create a new component instance; is needed by factory helper implementation.
 * @param xMgr service manager to if the components needs other component instances
 */
Reference< XInterface > SAL_CALL cMyWindow_create(
	const Reference< XMultiServiceFactory > & xMgr )
{
	if(DEBUG) printf("### cMyWindow_create begin ###\n");
	cMyWindow* pNew = new cMyWindow(xMgr);
	pNew->implLateInit();
	if(DEBUG) printf("### cMyWindow_create ending###\n");

	return Reference<XInterface>(static_cast< XSingleServiceFactory* >(pNew));
}

void cMyWindow::implLateInit()
{
	if(DEBUG) printf("### implLateInit begin ###\n");
	{
	Reference< XInterface > xThis(static_cast< XSingleServiceFactory* >(this), UNO_QUERY);
	Reference< XWindowListener > xWL(xThis, UNO_QUERY);
	if(xWL.is()) {
		if(DEBUG>1) printf("*** received XWindowListener by xThis ***\n");
		}
	else {
		printf("*** couldn't get XWL :-( ***\n");
		}


	TabListenerImpl* xTabListenerImpl = new ::TabListenerImpl(xThis);
	m_xTabListener = static_cast< XTabListener *> (xTabListenerImpl);
        
	m_xTabControl->addTabListener(m_xTabListener);

        Reference< css::beans::XPropertySet > xTabProp(m_xTabControl, UNO_QUERY_THROW);
        Any aTabProp = xTabProp->getPropertyValue(::rtl::OUString::createFromAscii("ParentWindow"));

        aTabProp >>= m_xTabParentWindow;
	aTabProp = xTabProp->getPropertyValue(::rtl::OUString::createFromAscii("TopWindow"));
	aTabProp >>= m_xTopWindow;
	if(!m_xTopWindow.is()) printf("*** TopWindow not retrieved ***\n");
		else if(DEBUG>1) printf("*** TopWindow retrieved properly ***\n");

	m_xTopWindow->addTopWindowListener(Reference< XTopWindowListener >(xThis, UNO_QUERY));
	m_xTabParentWindow->addWindowListener(xWL);

	if(DEBUG) printf("### implLateInit end ###\n"); fflush(stdout);

	}


}
//##################################################################################################
//#### EXPORTED ####################################################################################
//##################################################################################################


/**
 * Gives the environment this component belongs to.
 */
extern "C" void SAL_CALL component_getImplementationEnvironment(const sal_Char ** ppEnvTypeName, uno_Environment ** ppEnv)
{
	*ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
}

/**
 * This function creates an implementation section in the registry and another subkey
 *
 * for each supported service.
 * @param pServiceManager   the service manager
 * @param pRegistryKey      the registry key
 */
extern "C" sal_Bool SAL_CALL component_writeInfo(void * pServiceManager, void * pRegistryKey)
{
	sal_Bool result = sal_False;

	if (pRegistryKey)
	{
		try
		{
			Reference< XRegistryKey > xNewKey(
				reinterpret_cast< XRegistryKey * >( pRegistryKey )->createKey(
					OUString( RTL_CONSTASCII_USTRINGPARAM("/" IMPLNAME "/UNO/SERVICES") ) ) );

			const Sequence< OUString > & rSNL =
				cMyWindow::getSupportedServiceNames_Static();
			const OUString * pArray = rSNL.getConstArray();
			for ( sal_Int32 nPos = rSNL.getLength(); nPos--; )
				xNewKey->createKey( pArray[nPos] );

			return sal_True;
		}
		catch (InvalidRegistryException &)
		{
			// we should not ignore exceptions
		}
	}
	return result;
}

/**
 * This function is called to get service factories for an implementation.
 *
 * @param pImplName       name of implementation
 * @param pServiceManager a service manager, need for component creation
 * @param pRegistryKey    the registry key for this component, need for persistent data
 * @return a component factory
 */
extern "C" void * SAL_CALL component_getFactory(const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey)
{
	void * pRet = 0;

    if(DEBUG) printf("component_getFactory() starts ...\n");
	if (rtl_str_compare( pImplName, IMPLNAME ) == 0)
	{
        if(DEBUG) printf("right impl name\n");
		Reference< XSingleServiceFactory > xFactory( createOneInstanceFactory(
			reinterpret_cast< XMultiServiceFactory * >( pServiceManager ),
			OUString( RTL_CONSTASCII_USTRINGPARAM(IMPLNAME) ),
			cMyWindow_create,
			cMyWindow::getSupportedServiceNames_Static() ) );

		if (xFactory.is())
		{
			xFactory->acquire();
			pRet = xFactory.get();
		}
	}

    if(DEBUG) printf("component_getFactory() finished with pRet=%d\n", pRet);
	return pRet;
}
